#include							"TcpSocket.h"
#include <boost/pointer_cast.hpp>
#include <boost/shared_ptr.hpp>

TcpSocket::TcpSocket(boost::asio::io_service & service, unsigned int id) : _socket(service), ASocket(id)
{
  _type = ASocket::TCP;
}

TcpSocket::~TcpSocket()
{
  std::cout << "[INFO] Socket destroyed" << std::endl;
}

void								TcpSocket::_receive_size(const boost::system::error_code & error, size_t size)
{
  if (!error && size == sizeof(unsigned short))
  {
    _getOrderSize();
    _startRead();
  }
  else
    close();
}

void								TcpSocket::_receive_data(const boost::system::error_code & error, size_t size)
{
  if (!error && size == _current_msg)
  {
    this->_handler->harvest(this);
    _startRead();
  }
  else
    close();
}

void								TcpSocket::start()
{
  _startRead();
}

void								TcpSocket::close()
{
  _socket.close();
  _handler->disconnect(this);
}

boost::asio::ip::tcp::socket		&TcpSocket::getSocket()
{
	return _socket;
}

void								TcpSocket::_startRead()
{
  if (_socket.is_open())
    {
      if (!_current_msg)
	boost::asio::async_read(_socket, boost::asio::buffer(_buffer, sizeof(_current_msg)),
				boost::bind(&TcpSocket::_receive_size, shared_from_this(), boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred));
      else if (_current_msg > 0)
	boost::asio::async_read(_socket, boost::asio::buffer(_buffer, _current_msg), 
				boost::bind(&TcpSocket::_receive_data, shared_from_this(), boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred));
    }
  else
    this->close();
}

void								TcpSocket::write(byte *data, size_t size)
{
  boost::asio::async_write(_socket, boost::asio::buffer(data, size), boost::bind(&TcpSocket::_handle_write, shared_from_this(), boost::asio::placeholders::error));
}

std::string							TcpSocket::getIp() const
{
    return _socket.remote_endpoint().address().to_string();
}

TcpSocket::SocketPtr					       	TcpSocket::create(boost::asio::io_service& ios, unsigned int id)
{
  return TcpSocket::SocketPtr(new TcpSocket(ios, id));
}
